#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cre.h"
#include "li_basic.h"

void init_re_module()
{

}

Li_List __split(void* pattern__or__re,
	char* subject,
	int max_split,
	int flags,
	int mode_re)

{
	int sub_length = strlen(subject);
	int j2 = 0;
	int _m_n = 0, m_n = 0;
	int brackets = -1;
	int** vcs;
	if (mode_re)
		vcs = re_searchall2((pcre*)pattern__or__re, subject, sub_length, &_m_n, &brackets, flags);
	else
		vcs = re_searchall((char*)pattern__or__re, subject, sub_length, &_m_n, &brackets, flags);
	m_n = _m_n;
	char* b = NULL;
	if (!vcs)
	{
		return NULL;
	}
	if (max_split && max_split < m_n)
		m_n = max_split;
	Li_List list = new_li(char*);
	int start = 0;

	if (brackets == 1)
	{
		for (int i = 0; i < m_n; i++)
		{
			int* v = vcs[i];
			int length = v[0] - start;
			b = malloc(length + 1);
			if (!b)
				goto e_er;
			b[length] = 0;
			if (length)
				memcpy(b, subject + start, length);
			li_add(list, b);
			start = v[1];
		}
		if (start <= sub_length)
		{
			b = new_string_by(subject + start);
			li_add(list, b);
		}
		goto exit;
	}

	for (int i = 0; i < m_n; i++)
	{
		int* v = vcs[i];
		int length = v[0] - start;
		b = malloc(length + 1);
		if (!b)
			goto e_er;
		memcpy(b, subject + start, length);
		b[length] = 0;
		li_add(list, b);

		for (int j = 1; j < brackets; j++)
		{
			j2 = j * 2;
			int length2 = v[j2 + 1] - v[j2];
			b = malloc(length2 + 1);
			if (!b)
				goto e_er;
			b[length2] = 0;
			memcpy(b, subject + v[j2], length2);
			li_add(list, b);
		}
		start = v[1];
	}
	if (start <= sub_length)
	{
		b = new_string_by(subject + start);
		li_add(list, b);
	}
	goto exit;
e_er:
	if (list)
	{
		delete_list_recursively(list);
		list = NULL;
	}
exit:
	if (vcs)
		re_free_searchall(vcs, _m_n);
	return list;
}

void* __findall(void* pattern__or__re,
	char* subject,
	int flags,
	int mode_re)
{
	int length = strlen(subject);
	int j2 = 0;
	int m_n = -1;
	int brackets = -1;
	int** vcs;
	if (mode_re)
		vcs = re_searchall2((pcre*)pattern__or__re, subject, length, &m_n, &brackets, flags);
	else
		vcs = re_searchall((char*)pattern__or__re, subject, length, &m_n, &brackets, flags);

	char* b = NULL;
	if (!vcs)
	{
		if (m_n < 0) // error
			return NULL;
		return NULL;
	}
	Li_List list = new_li(char*);

	for (int i = 0; i < m_n; i++)
	{
		int* v = vcs[i];
		length = v[1] - v[0];
		b = malloc(length + 1);
		if (!b)
			goto e_er;
		b[length] = 0;
		if (length)
			memcpy(b, subject + v[0], length);
		li_add(list, b);
	}
	goto exit;
e_er:
	if (list)
	{
		delete_list_recursively(list);
		list = NULL;
	}
exit:
	if (vcs)
		re_free_searchall(vcs, m_n);
	return list;
}

char* __subn(void* pattern__or__re,
	char* repl,
	char* subject,
	int count,
	int flags,
	int mode_re)
{
	int length = strlen(subject);
	int matched_times = 0;
	char* s;
	if (mode_re)
		s = re_subn2((pcre*)pattern__or__re, repl, subject, length, count, flags, &matched_times);
	else
		s = pcre_subn((char*)pattern__or__re, repl, subject, length, count, flags, &matched_times);

	if (!s)
	{
		return NULL;
	}
	if (s == subject)
	{
		return new_string_by(s);
	}
	return s;
}